<?php

namespace core\notice;


use yii\caching\Cache;

class Queue
{

    const PREFIX = 'notice_queue_';

    const KEY_HEAD = '_head';

    const KEY_TAIL = '_tail';

    const START = 0;

    /** @var int 过期时间 */
    const DURATION = 7200;

    /** @var Cache */
    private static $cache = null;

    private static function getCache()
    {
        if (empty(self::$cache)) {
            self::$cache = \Yii::$app->getCache();
        }
        return self::$cache;
    }

    private static function getHeadKey($queueName)
    {
        return self::PREFIX . $queueName . self::KEY_HEAD;
    }

    private static function getTailKey($queueName)
    {
        return self::PREFIX . $queueName . self::KEY_TAIL;
    }

    private static function getQueueKey($queue, $id)
    {
        return self::PREFIX . $queue . '_' . $id;
    }

    private static function getDuration()
    {
        $duration = \Yii::$app->params['notice']['duration'];
        return empty($duration) ? self::DURATION : $duration;
    }

    private static function get($key)
    {
        return self::getCache()->get($key);
    }

    private static function set($key, $value, $duration = 0)
    {
        return self::getCache()->set($key, $value, $duration);
    }

    public static function enqueue($data, $queue)
    {
        $tailKey = self::getTailKey($queue);
        $tail = self::get($tailKey);
        if ($tail === false) {
            self::init($queue);
            $tail = self::START;
        } else {
            $tail += 1;
            self::set($tailKey, $tail);
        }
        // 入队
        $queueItemKey = self::getQueueKey($queue, $tail);
        self::set($queueItemKey, $data, self::getDuration());
    }

    public static function dequeueAll($queue)
    {
        $results = [];
        $headID = self::get(self::getHeadKey($queue));
        $tailID = self::get(self::getTailKey($queue));
        if (!($headID === false || $tailID === false || $headID > $tailID)) {
            for ($i = $headID; $i <= $tailID; $i++) {
                $item = self::get(self::getQueueKey($queue, $i));
                if ($item === false) {
                    // 数据丢失
                }
                $results[] = $item;
            }
        }
        // 删除队列
        self::destory($queue);
        return $results;
    }

    private static function init($queue)
    {
        self::set(self::getTailKey($queue), self::START);
        self::set(self::getHeadKey($queue), self::START);
    }

    private static function destory($queue)
    {
        self::getCache()->delete(self::getTailKey($queue));
        self::getCache()->delete(self::getHeadKey($queue));
    }
}